
import numpy as np
import matplotlib.pyplot as plt

def load_data_set():
    data_mat = []
    label_mat = []
    fr = open('testSet.txt')
    for line in fr.readlines():
        line_arr = line.strip().split()
        data_mat.append([1.0, float(line_arr[0]), float(line_arr[1])])
        label_mat.append(int(line_arr[2]))

    return data_mat, label_mat

def sigmoid(in_x):
    return 1.0 / (1 + np.exp(-in_x))

def grad_ascent(data_mat_in, class_labels):
    data_matrix = np.mat(data_mat_in)
    label_mat = np.mat(class_labels).transpose()
    m,n = np.shape(data_matrix)
    alpha = 0.001
    max_cycles = 500
    weights = np.ones((n, 1))

    for k in range(max_cycles):
        h = sigmoid(data_matrix * weights)  # h 为100x1的矩阵
        error = (label_mat - h)             # erroe 100x1的矩阵
        # data_matrix.transpose()*error 为代价函数对weight的导数
        weights = weights + alpha * data_matrix.transpose() * error
        # if k % 50 == 0:
        #     plot_best_fit(weights)

    return weights


def stoc_grad_ascent(data_mat_in, class_labels):
    data_matrix = np.array(data_mat_in)
    m,n = np.shape(data_matrix)
    alpha = 0.001
    max_cycles = 500
    weights = np.ones(n)
    for k in range(max_cycles):
        for i in range(m):
            h = sigmoid(sum(data_matrix[i] * weights))
            error = class_labels[i] - h
            weights = weights + alpha * error * data_matrix[i]

    return weights


def stoc_grad_ascent1(data_mat_in, class_labels, num_iter=150):
    data_matrix = np.array(data_mat_in)
    m,n = np.shape(data_matrix)
    alpha = 0.001
    weights = np.ones(n)
    for k in range(num_iter):
        data_index = range(m)
        for i in range(m):
            alpha = 4 / (1.0 + k + i) + 0.01
            rand_index = int(np.random.uniform(0, len(data_index)))
            h = sigmoid(sum(data_matrix[rand_index] * weights))
            error = class_labels[rand_index] - h
            weights = weights + alpha * error * data_matrix[rand_index]

    return weights


def plot_best_fit(wei):

    weights = wei  # .getA()  # 矩阵转换为数组
    data_mat, label_mat = load_data_set()
    data_arr = np.array(data_mat)
    n = np.shape(data_arr)[0]

    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []

    for i in range(n):
        if int(label_mat[i]) == 1:
            xcord1.append(data_arr[i, 1])
            ycord1.append(data_arr[i, 2])
        else:
            xcord2.append(data_arr[i, 1])
            ycord2.append(data_arr[i, 2])

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s = 30, c = 'r', marker = 's')
    ax.scatter(xcord2, ycord2, s = 30, c = 'g')

    x = np.arange(-3.0, 3.0, 0.1)
    y = (-weights[0] - weights[1] * x) / weights[2]

    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()


def classify_vector(in_x, weights):
    prob = sigmoid((sum(in_x * weights)))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0


def colic_test():
    frTrain = open('horseColicTraining.txt'); 
    frTest = open('horseColicTest.txt')
    trainingSet = []
    trainingLabels = []

    for line in frTrain.readlines():
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[21]))
    trainWeights = stoc_grad_ascent1(trainingSet, trainingLabels, 1000)
    # trainWeights = grad_ascent(trainingSet, trainingLabels)
    errorCount = 0
    numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classify_vector(np.array(lineArr), trainWeights))!= int(currLine[21]):
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec)
    print ("the error rate of this test is: %f" % errorRate)
    return errorRate



if __name__ == '__main__':
    # data_mat, label_mat = load_data_set()
    # weights = grad_ascent(data_mat, label_mat)
    # plot_best_fit(weights.getA())
    # weights = stoc_grad_ascent(data_mat, label_mat)
    # plot_best_fit(weights)
    # weights = stoc_grad_ascent1(data_mat, label_mat)
    # plot_best_fit(weights)

    colic_test()
    